package org.execute.tool.键鼠工具;

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

public class BasicInputDemo {
    private static Robot robot;
    private static final Random random = new Random();
    // ====================== 新增：主动中断标志位（volatile确保多线程可见性）======================
    private static volatile boolean isInterrupted = false;





    // ====================== 原有工具方法（不变）======================
    public static void main(String[] args) {
        try {
            robot = new Robot();
            robot.delay(1000);

            // ---------------------- 演示1：命令失败触发中断 ----------------------
            System.out.println("=== 演示：命令失败中断 ===");
            List<InputCommand> failInterruptGroup = new ArrayList<>();
            // 命令1：正常移动（成功）
            Map<String, Object> moveParams = new HashMap<>();
            moveParams.put("x", 884);
            moveParams.put("y", 840);
            failInterruptGroup.add(new InputCommand(CommandType.MOVE_TO, moveParams));
            // 命令2：故意传入错误参数（模拟失败，触发中断）
            Map<String, Object> errorClickParams = new HashMap<>();
            errorClickParams.put("button", "错误参数（应为整数）"); // 故意传字符串，触发类型转换异常
            failInterruptGroup.add(new InputCommand(CommandType.MOUSE_CLICK, errorClickParams));
            // 命令3：若不中断会执行，但因命令2失败，此命令不会执行
            Map<String, Object> textParams = new HashMap<>();
            textParams.put("text", "此命令不会执行（因前序命令失败）");
            failInterruptGroup.add(new InputCommand(CommandType.TYPE_TEXT, textParams));
            // 执行（命令2失败后会中断，命令3不执行）
            executeCommandGroup(failInterruptGroup);
            robot.delay(2000); // 等待观察


            // ---------------------- 演示2：主动触发中断（多线程模拟） ----------------------
            System.out.println("\n=== 演示：主动中断 ===");
            List<InputCommand> activeInterruptGroup = new ArrayList<>();
            // 命令1：移动到(500,500)
            Map<String, Object> move2Params = new HashMap<>();
            move2Params.put("x", 500);
            move2Params.put("y", 500);
            activeInterruptGroup.add(new InputCommand(CommandType.MOVE_TO, move2Params));
            // 命令2：延迟3秒（模拟耗时操作，期间触发主动中断）
            Map<String, Object> longDelayParams = new HashMap<>();
            longDelayParams.put("delayMs", 3000);
            activeInterruptGroup.add(new InputCommand(CommandType.DELAY, longDelayParams));
            // 命令3：若不中断会执行，主动中断后不执行
            Map<String, Object> text2Params = new HashMap<>();
            text2Params.put("text", "此命令不会执行（因主动中断）");
            activeInterruptGroup.add(new InputCommand(CommandType.TYPE_TEXT, text2Params));

            // 线程1：执行命令组
            new Thread(() -> executeCommandGroup(activeInterruptGroup)).start();
            // 线程2：1秒后主动触发中断
            new Thread(() -> {
                try {
                    Thread.sleep(1000); // 等待1秒后中断
                    interruptCommandGroup();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();

        } catch (AWTException e) {
            System.err.println("无法初始化Robot类: " + e.getMessage());
            e.printStackTrace();
        }
    }
    // ====================== 3. 核心：命令组执行函数（新增中断逻辑）======================
    /**
     * 执行一组键鼠命令（支持失败中断和主动中断）
     * @param commandList 命令列表
     */
    public static void executeCommandGroup(List<InputCommand> commandList) {
        if (commandList == null || commandList.isEmpty()) {
            System.err.println("命令组为空，无需执行");
            return;
        }

        // 执行前重置中断标志（避免上次中断状态影响）
        resetInterrupt();
        System.out.println("开始执行命令组（共" + commandList.size() + "个命令）：");

        for (int i = 0; i < commandList.size(); i++) {
            // 检查：若主动中断标志为true，立即终止执行
            if (isInterrupted) {
                System.err.println("命令组执行中断：检测到主动中断信号");
                return;
            }

            InputCommand command = commandList.get(i);
            CommandType type = command.getCommandType();
            Map<String, Object> params = command.getParams();

            try {
                System.out.printf("执行命令 %d/%d：【%s】%n", i + 1, commandList.size(), type.getDesc());
                // 命令执行逻辑（不变）
                switch (type) {
                    case MOVE_TO:
                        int x = (int) params.get("x");
                        int y = (int) params.get("y");
                        moveMouseTo(x, y);
                        break;
                    case MOVE_RELATIVE:
                        int dx = (int) params.get("dx");
                        int dy = (int) params.get("dy");
                        moveMouseRelative(dx, dy);
                        break;
                    case MOUSE_CLICK:
                        int button = (int) params.get("button");
                        mouseClick(button);
                        break;
                    case TYPE_TEXT:
                        String text = (String) params.get("text");
                        typeText(text);
                        break;
                    case PRESS_KEY:
                        Object keyObj = params.get("key");
                        if (keyObj instanceof Integer) {
                            pressKey((int) keyObj);
                        } else if (keyObj instanceof String) {
                            pressKey((String) keyObj);
                        } else {
                            throw new IllegalArgumentException("按键参数类型错误，需为Integer(keyCode)或String(关键词)");
                        }
                        break;
                    case PRESS_COMBINATION:
                        int[] modifiers = (int[]) params.get("modifiers");
                        int comboKey = (int) params.get("key");
                        pressCombinationKeys(modifiers, comboKey);
                        break;
                    case DELAY:
                        int delayMs = (int) params.get("delayMs");
                        // 延迟期间也检查中断（避免长时间延迟无法终止）
                        for (int d = 0; d < delayMs; d += 100) {
                            if (isInterrupted) {
                                System.err.println("命令组执行中断：延迟期间检测到主动中断信号");
                                return;
                            }
                            robot.delay(100);
                        }
                        break;
                    default:
                        throw new UnsupportedOperationException("不支持的命令类型：" + type.getDesc());
                }
            } catch (Exception e) {
                // 新增：命令失败时中断整个命令组，不再执行后续命令
                System.err.printf("命令 %d/%d 执行失败：%s%n", i + 1, commandList.size(), e.getMessage());
                e.printStackTrace();
                System.err.println("命令组执行中断：因单个命令失败触发中断");
                return; // 终止循环，中断命令组
            }
        }
        System.out.println("命令组执行完成！");
    }

    // ====================== 新增：主动中断相关方法======================
    /**
     * 主动触发命令组中断（外部调用，如线程、按钮）
     */
    public static void interruptCommandGroup() {
        isInterrupted = true;
        System.out.println("已发送主动中断信号，命令组将在下次检查时终止");
    }

    /**
     * 重置中断标志（用于下次执行命令组前清空状态）
     */
    private static void resetInterrupt() {
        isInterrupted = false;
    }
    // 以下原有方法（moveMouseTo、moveMouseRelative、mouseClick等）保持不变，省略重复代码...
    private static void moveMouseTo(int x, int y) {
        robot.mouseMove(x, y);
    }

    private static void moveMouseToCenter() {
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        int centerX = screenSize.width / 2;
        int centerY = screenSize.height / 2;
        robot.mouseMove(centerX, centerY);
    }

    private static void moveMouseRelative(int dx, int dy) {
        Point currentPos = java.awt.MouseInfo.getPointerInfo().getLocation();
        robot.mouseMove(currentPos.x + dx, currentPos.y + dy);
    }

    private static void mouseClick(int button) {
        robot.mousePress(button);
        robot.delay(50);
        robot.mouseRelease(button);
    }

    private static void pressKey(int keyCode) {
        robot.keyPress(keyCode);
        int delay = 30 + random.nextInt(71);
        robot.delay(delay);
        robot.keyRelease(keyCode);
    }

    private static void pressKey(String key) {
        int keyCode = getKeyCodeFromKeyword(key);
        if (keyCode != KeyEvent.VK_UNDEFINED) {
            pressKey(keyCode);
        } else {
            System.err.println("不支持的按键关键词: " + key);
        }
    }

    private static void typeText(String text) {
        typeViaClipboard(text);
    }

    private static void typeViaClipboard(String text) {
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        Transferable original = clipboard.getContents(null);

        try {
            StringSelection selection = new StringSelection(text);
            clipboard.setContents(selection, null);

            robot.keyPress(KeyEvent.VK_CONTROL);
            robot.keyPress(KeyEvent.VK_V);
            robot.delay(50);
            robot.keyRelease(KeyEvent.VK_V);
            robot.keyRelease(KeyEvent.VK_CONTROL);
            robot.delay(100);
        } finally {
            if (original != null) {
                clipboard.setContents(original, null);
            }
        }
    }

    private static void pressCombinationKeys(int[] modifierKeys, int key) {
        for (int modifier : modifierKeys) {
            robot.keyPress(modifier);
        }

        robot.keyPress(key);
        robot.delay(50);
        robot.keyRelease(key);

        for (int i = modifierKeys.length - 1; i >= 0; i--) {
            robot.keyRelease(modifierKeys[i]);
        }
    }

    private static int getKeyCodeFromKeyword(String key) {
        if (key == null || key.isEmpty()) {
            return KeyEvent.VK_UNDEFINED;
        }

        switch (key.toUpperCase()) {
            case "ENTER": return KeyEvent.VK_ENTER;
            case "TAB": return KeyEvent.VK_TAB;
            case "BACKSPACE": return KeyEvent.VK_BACK_SPACE;
            case "ESC": case "ESCAPE": return KeyEvent.VK_ESCAPE;
            case "SPACE": return KeyEvent.VK_SPACE;
            case "SHIFT": return KeyEvent.VK_SHIFT;
            case "CTRL": return KeyEvent.VK_CONTROL;
            case "ALT": return KeyEvent.VK_ALT;
            case "CAPS_LOCK": return KeyEvent.VK_CAPS_LOCK;
            case "UP": return KeyEvent.VK_UP;
            case "DOWN": return KeyEvent.VK_DOWN;
            case "LEFT": return KeyEvent.VK_LEFT;
            case "RIGHT": return KeyEvent.VK_RIGHT;
            case "F1": return KeyEvent.VK_F1;
            case "F2": return KeyEvent.VK_F2;
            case "F3": return KeyEvent.VK_F3;
            case "F4": return KeyEvent.VK_F4;
            case "F5": return KeyEvent.VK_F5;
            case "F6": return KeyEvent.VK_F6;
            case "F7": return KeyEvent.VK_F7;
            case "F8": return KeyEvent.VK_F8;
            case "F9": return KeyEvent.VK_F9;
            case "F10": return KeyEvent.VK_F10;
            case "F11": return KeyEvent.VK_F11;
            case "F12": return KeyEvent.VK_F12;
        }

        if (key.length() == 1) {
            char c = key.charAt(0);
            if (Character.isLetter(c)) {
                return KeyEvent.getExtendedKeyCodeForChar(Character.toUpperCase(c));
            }
            if (Character.isDigit(c)) {
                return KeyEvent.getExtendedKeyCodeForChar(c);
            }
        }

        return KeyEvent.VK_UNDEFINED;
    }
}